﻿using System;
using System.Collections.Generic;
using System.Linq;
using Styx.Common;
using Styx.CommonBot;
using Styx.WoWInternals;
using Styx.WoWInternals.WoWObjects;

namespace TuanHA_Combat_Routine
{
    public partial class Classname
    {
        #region SpellsCooldownHS

        //private static readonly HashSet<string> SpellsCooldownHS = new HashSet<string>
        //    {
        //        //Racial
        //        "Arcane Torrent",
        //        "Berserking",
        //        "Blood Fury",
        //        "Cannibalize",
        //        "Darkflight",
        //        "Escape Artist",
        //        "Every Man for Himself",
        //        "Gift of the Naaru",
        //        "Rocket Jump",
        //        "Shadowmeld",
        //        "Stoneform",
        //        "War Stomp",
        //        "Will of the Forsaken",

        //        //Class Spells
        //        //"Avenger's Shield",
        //        "Avenging Wrath",
        //        "Ardent Defender",
        //        "Blinding Light",
        //        "Beacon of Light",
        //        "Consecration",
        //        "Crusader Strike",
        //        "Devotion Aura",
        //        "Divine Favor ",
        //        "Divine Plea",
        //        "Divine Protection",
        //        "Divine Shield",
        //        "Execution Sentence",
        //        "Fist of Justice",
        //        "Guardian of Ancient Kings",
        //        "Hammer of Justice",
        //        "Hammer of the Righteous",
        //        //"Hammer of Wrath",
        //        "Hand of Freedom",
        //        "Hand of Protection",
        //        "Hand of Purity",
        //        "Hand of Sacrifice",
        //        "Hand of Salvation",
        //        "Holy Avenger",
        //        "Holy Prism",
        //        "Holy Shock", //It reset
        //        "Judgment",
        //        "Lay on Hands",
        //        "Light's Hammer",
        //        "Rebuke",
        //        "Reckoning",
        //        "Repentance",
        //        "Sacred Shield",
        //        "Speed of Light",
        //        "Turn Evil",
        //    };
        private static readonly HashSet<string> SpellsCooldownHS = new HashSet<string> { 
            "Arcane Torrent", "Berserking", "Blood Fury", "Cannibalize", "Darkflight", "Escape Artist", "Every Man for Himself", "Gift of the Naaru", "Rocket Jump", "Shadowmeld", "Stoneform", "War Stomp", "Will of the Forsaken", "Avenging Wrath", "Ardent Defender", "Blinding Light", 
            "Beacon of Light", "Consecration", "Crusader Strike", "Devotion Aura", "Divine Favor ", "Divine Plea", "Divine Protection", "Divine Shield", "Execution Sentence", "Fist of Justice", "Guardian of Ancient Kings", "Hammer of Justice", "Hammer of the Righteous", "Hand of Freedom", "Hand of Protection", "Hand of Purity", 
            "Hand of Sacrifice", "Hand of Salvation", "Holy Avenger", "Holy Prism", "Holy Shock", "Judgment", "Lay on Hands", "Light's Hammer", "Rebuke", "Reckoning", "Repentance", "Sacred Shield", "Speed of Light", "Turn Evil"
         };
        #endregion

        #region ClearEnemyandFriendListCache

        //private static void ClearEnemyandFriendListCacheEvent(object sender, LuaEventArgs args)
        //{
        //    GlobalCheckTime = DateTime.Now - TimeSpan.FromSeconds(30.0);
        //    EnemyListCache.Clear();
        //    FriendListCache.Clear();
        //}

        #endregion

        #region EnemyListCache
        private static DateTime EnemyListCacheClearLast;
        private static readonly Dictionary<ulong, DateTime> EnemyListCache = new Dictionary<ulong, DateTime>();

        //private static void EnemyListCacheClear()
        //{
        //    if (EnemyListCacheClearLast <= DateTime.Now)
        //    {
        //        EnemyListCacheClearLast = DateTime.Now + TimeSpan.FromSeconds(5.0);
        //        foreach (ulong num in (from unit in EnemyListCache
        //                               where unit.Value < DateTime.Now
        //                               select unit.Key).ToList<ulong>())
        //        {
        //            EnemyListCache.Remove(num);
        //        }
        //    }
        //}

        //private static void EnemyListCacheAdd(WoWUnit unit, int expireSeconds = 10)
        //{
        //    if ((!MeHasAura("Arena Preparation") && !MeHasAura("Preparation")) && !EnemyListCache.ContainsKey(unit.Guid))
        //    {
        //        EnemyListCache.Add(unit.Guid, DateTime.Now + TimeSpan.FromSeconds((double)expireSeconds));
        //    }
        //}

        #endregion

        #region FriendListCache

        private static readonly Dictionary<ulong, DateTime> FriendListCache = new Dictionary<ulong, DateTime>();
        private static DateTime FriendListCacheClearLast;
        //private static void FriendListCacheClear()
        //{
        //    if (FriendListCacheClearLast <= DateTime.Now)
        //    {
        //        FriendListCacheClearLast = DateTime.Now + TimeSpan.FromSeconds(5.0);
        //        foreach (ulong num in (from unit in FriendListCache
        //                               where unit.Value < DateTime.Now
        //                               select unit.Key).ToList<ulong>())
        //        {
        //            FriendListCache.Remove(num);
        //        }
        //    }
        //}

        //private static void FriendListCacheAdd(WoWUnit unit, int expireSeconds = 60)
        //{
        //    if (!FriendListCache.ContainsKey(unit.Guid))
        //    {
        //        FriendListCache.Add(unit.Guid, DateTime.Now + TimeSpan.FromSeconds((double)expireSeconds));
        //    }
        //}

        #endregion

        #region InLineOfSpellSightCache

        private static readonly Dictionary<ulong, DateTime> InLineOfSpellSightCache = new Dictionary<ulong, DateTime>();

        private static void InLineOfSpellSightCacheClear()
        {
            foreach (ulong num in (from unit in InLineOfSpellSightCache
                                   where unit.Value < DateTime.Now
                                   select unit.Key).ToList<ulong>())
            {
                InLineOfSpellSightCache.Remove(num);
            }
        }

        private static void InLineOfSpellSightCacheAdd(WoWUnit unit, int expireMilliseconds = 100)
        {
            if (!InLineOfSpellSightCache.ContainsKey(unit.Guid))
            {
                InLineOfSpellSightCache.Add(unit.Guid, DateTime.Now + TimeSpan.FromMilliseconds((double)expireMilliseconds));
            }
        }

        private static bool InLineOfSpellSightCheck(WoWUnit unit)
        {
            if ((unit == null) || !unit.IsValid)
            {
                return false;
            }
            InLineOfSpellSightCacheClear();
            if ((unit != Me) && !InLineOfSpellSightCache.ContainsKey(unit.Guid))
            {
                if (!unit.InLineOfSpellSight)
                {
                    return false;
                }
                if (InRaid || InDungeon)
                {
                    InLineOfSpellSightCacheAdd(unit, 300);
                    return true;
                }
                InLineOfSpellSightCacheAdd(unit, 100);
            }
            return true;
        }

        #endregion

        #region CanCastCache

        private static readonly Dictionary<string, DateTime> SpellsCooldownCache = new Dictionary<string, DateTime>();
        //private static DateTime SkipOnGcdSpellCheck;
        private static DateTime spellCooldownBack;

        private static void SpellsCooldownCacheAdd(string spellName, DateTime spellCooldownBack)
        {
            if ((spellName == "Ice Trap") || (spellName == "Freezing Trap"))
            {
                SpellsCooldownCache.Add("Ice Trap", spellCooldownBack);
                SpellsCooldownCache.Add("Freezing Trap", spellCooldownBack);
            }
            else
            {
                SpellsCooldownCache.Add(spellName, spellCooldownBack);
            }
        }

        private static void SpellsCooldownCacheClear()
        {
            if (MeHasAura("Arena Preparation"))
            {
                SpellsCooldownCache.Clear();
            }
            else
            {
                foreach (string str in (from unit in SpellsCooldownCache
                                        where unit.Value < DateTime.Now
                                        select unit.Key).ToList<string>())
                {
                    try
                    {
                        SpellsCooldownCache.Remove(str);
                    }
                    catch (Exception)
                    {
                        Styx.Common.Logging.Write("Fail to SpellsCooldownCache.Remove({0})", new object[] { str });
                        throw;
                    }
                }
            }
        }

        private static bool CanCastCheck(string spellName, bool IsOffGCDSpell = false)
        {
            SpellsCooldownCacheClear();
            if (!SpellsCooldownCache.ContainsKey(spellName))
            {
                bool flag;
                if (!SpellManager.HasSpell(spellName))
                {
                    return false;
                }
                if ((spellName == "Death Grip") && MeHasAura(0x201db))
                {
                    return true;
                }
                if ((InArena || InBattleground) && ((((spellName != "Lichborne") && (spellName != " Icebound Fortitude")) && ((spellName != "Desecrated Ground") && (spellName != "Every Man for Himself"))) && DebuffCC(Me)))
                {
                    return false;
                }
                double spellPowerCost = GetSpellPowerCost(spellName);
                if (spellPowerCost < 1.0)
                {
                    flag = false;
                }
                else
                {
                    flag = true;
                }
                if (flag)
                {
                    if (((spellName == "Death Coil") && MeHasAura(0x13dbc)) && MeHasAura("Unholy Presence"))
                    {
                        spellPowerCost = 0.0;
                    }
                    if (PlayerRunicPower() < spellPowerCost)
                    {
                        return false;
                    }
                }
                if ((spellName != "Army of the Dead") || !IsMoving(Me))
                {
                    if (SpellManager.CanCast(spellName))
                    {
                        return true;
                    }
                    spellCooldownBack = (DateTime.Now + GetSpellCooldown(spellName)) - TimeSpan.FromMilliseconds(MyLatency);
                    SpellsCooldownCacheAdd(spellName, spellCooldownBack);
                }
            }
            return false;
        }

        #endregion

        #region CanUseCache

        private static readonly Dictionary<WoWItem, DateTime> ItemsCooldownCache = new Dictionary<WoWItem, DateTime>();
        
        private static DateTime ItemCooldownBack;

        private static TimeSpan GetItemCooldown(WoWItem item)
        {
            if (!string.IsNullOrEmpty(Lua.GetReturnVal<string>("return GetItemSpell(" + item.Entry + ")", 0)) && item.Usable)
            {
                return item.CooldownTimeLeft;
            }
            return TimeSpan.FromMinutes(1.0);
        }

        private static void ItemsCooldownCacheAdd(WoWItem itemName, DateTime ItemCooldownBack)
        {
            ItemsCooldownCache.Add(itemName, ItemCooldownBack);
        }

        private static void ItemsCooldownCacheClear()
        {
            foreach (WoWItem item in (from unit in ItemsCooldownCache
                                      where unit.Value <= DateTime.Now
                                      select unit.Key).ToList<WoWItem>())
            {
                ItemsCooldownCache.Remove(item);
            }
        }

        private static bool CanUseCheck(WoWItem ItemName)
        {
            ItemsCooldownCacheClear();
            if (!ItemsCooldownCache.ContainsKey(ItemName))
            {
                ItemCooldownBack = DateTime.Now + GetItemCooldown(ItemName);
                if (ItemCooldownBack <= DateTime.Now)
                {
                    return true;
                }
                ItemsCooldownCacheAdd(ItemName, ItemCooldownBack);
            }
            return false;
        }

        #endregion
    }
}